//
//  IJKPlayVideoView.m
//  ijkPlayer
//
//  Created by apple on 2018/5/17.
//  Copyright © 2018年 锦. All rights reserved.
//

#import "IJKPlayVideoView.h"
#import <IJKMediaFramework/IJKMediaFramework.h>
#import <IJKMediaFramework/IJKMediaPlayback.h>

@interface IJKPlayVideoView()

@property (nonatomic, strong) IJKFFOptions *options;
@property (nonatomic, strong) IJKFFMoviePlayerController *ffMoviePlayerController;
@property (nonatomic, strong) IJKMediaUrlOpenData *data;

//用作预加载的player
@property (nonatomic, strong) IJKFFMoviePlayerController *prestrainPlayer;
@property (nonatomic, strong) IJKFFMoviePlayerController *prestrainLastPlayer;
//用作预加载的timer
@property (nonatomic, strong) NSTimer *presTrainTimer;
@end
@implementation IJKPlayVideoView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        self=[[[NSBundle mainBundle] loadNibNamed:@"IJKPlayVideoView" owner:self options:nil] firstObject];
        self.frame=frame;
        
        //初始化前一定要调用这个接口
        [IJKFFMoviePlayerController prehot];
        [IJKFFMoviePlayerController disableProxy:NO];
        
        //      [IJKFFMoviePlayerController checkIfFFmpegVersionMatch:YES];
        
        //这个一定要有，options 是对数据的处理，videotoolbox解码，设置音频视频等属性，都要有这个数据
        _options = [IJKFFOptions optionsByDefault];
        
        // 跳帧开关
        [_options setPlayerOptionIntValue:1 forKey:@"framedrop"];
        //某些视频在SeekTo的时候，会跳回到拖动前的位置，这是因为视频的关键帧的问题，通俗一点就是FFMPEG不兼容，视频压缩过于厉害，seek只支持关键帧，出现这个情况就是原始的视频文件中i 帧比较少
        [_options setPlayerOptionIntValue:1 forKey:@"enable-accurate-seek"];
        
        
        //        // app从后台进入前台都会调用这个方法 UIApplicationWillResignActiveNotification
        //        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationBecomeActive) name:UIApplicationWillEnterForegroundNotification object:nil];
        // 添加检测app进入后台的观察者
        //        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationEnterBackground) name: UIApplicationWillResignActiveNotification object:nil];
        
#pragma mark    ======== 预加载接受通知 ========
        //预加载时根据回调暂停
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(movieFirstVideoFrameRendered:) name:IJKMPMoviePlayerFirstVideoFrameRenderedNotification object:nil];
        
    }
    return self;
}
- (void)layoutSubviews{
    [super layoutSubviews];
    /**
     显示view的frame更新
     */
    _playView.frame = self.bounds;
}
- (void)applicationEnterBackground {
    [self.player pause];
}
- (void)applicationBecomeActive {
    
}
- (void)setUrlStr:(NSString *)urlStr {
    
    if (urlStr == nil) {
        return;
    }
    if (_prestrainPlayer) {
        [_prestrainPlayer shutdown];
        _prestrainPlayer = nil;
    }
    if (_prestrainLastPlayer) {
        [_prestrainLastPlayer shutdown];
        _prestrainLastPlayer = nil;
    }
    if (_player) {
        [_player shutdown];
        [_playView removeFromSuperview];
        _player = nil;
        _playView = nil;
    }
    
    _player = [[IJKFFMoviePlayerController alloc]initWithContentURLString:urlStr withOptions:_options];
    if (!_isFill) {
        _player.scalingMode = IJKMPMovieScalingModeAspectFit;
    }else{
        _player.scalingMode = IJKMPMovieScalingModeAspectFill;
    }
    
    /**
     要每次重新添加，否则不显示
     */
    UIView *playerView = [_player view];
    _playView = playerView;
    _playView.frame = self.frame;
    _playView.backgroundColor = [UIColor clearColor];
    [self insertSubview:_playView atIndex:0];
    [_player prepareToPlay];
    //    _player.shouldShowHudView = YES;
    
    
}



//- (void) playbackStateDidChange:(NSNotification *) notification {
//
//    //    NSLog(@"%@",notification);
//    //    IJKMPMoviePlaybackStateStopped,        停止
//    //    IJKMPMoviePlaybackStatePlaying,        正在播放
//    //    IJKMPMoviePlaybackStatePaused,         暂停
//    //    IJKMPMoviePlaybackStateInterrupted,    打断
//    //    IJKMPMoviePlaybackStateSeekingForward, 快进
//    //    IJKMPMoviePlaybackStateSeekingBackward 快退
//
//
//    switch (self.player.playbackState) {
//        case IJKMPMoviePlaybackStateStopped:
//            NSLog(@"停止");
//            break;
//        case IJKMPMoviePlaybackStatePlaying:
//            NSLog(@"正在播放");
//            break;
//        case IJKMPMoviePlaybackStatePaused:
//            NSLog(@"暂停");
//            break;
//        case IJKMPMoviePlaybackStateInterrupted:
//            NSLog(@"打断");
//            break;
//        case IJKMPMoviePlaybackStateSeekingForward:
//            NSLog(@"快进");
//            break;
//        case IJKMPMoviePlaybackStateSeekingBackward:
//            NSLog(@"快退");
//            break;
//        default:
//            break;
//    }
//}


#pragma mark    ======== IJKMediaPlayback ========
- (void)play {
    
    [_player play];
    
}
- (void)pause {
    
    [_player pause];
}
- (void)prepareToPlay {
    [_player prepareToPlay];
}
- (void)stop {
    [_player stop];
}
- (BOOL)isPlaying {
    return [_player isPlaying];
}
#pragma mark    ======== 预加载shutdown ========
//当退出播放器页面shutdown同时判断预加载的payer是否存在
- (void)shutdown {
    [_player shutdown];
    if (_prestrainPlayer) {
        [_prestrainPlayer shutdown];
        _prestrainPlayer = nil;
    }
    if (_prestrainLastPlayer) {
        [_prestrainLastPlayer shutdown];
        _prestrainLastPlayer = nil;
    }
    if (_presTrainTimer) {
        [_presTrainTimer invalidate];
        _presTrainTimer = nil;
    }
}
- (void)setPauseInBackground:(BOOL)pause {
    [_player setPauseInBackground:pause];
}
- (NSTimeInterval)currentTime {
    return _player.currentPlaybackTime;
}
- (void)setCurrentPlaybackRate:(CGFloat )rate {
    _player.playbackRate = rate;
}
- (NSTimeInterval)duration {
    return _player.duration;
}
- (void)seekTo:(CGFloat)time {
    _player.currentPlaybackTime = time;
}
- (UIImage *)thumbnailImageAtCurrentTime {
    return [_player thumbnailImageAtCurrentTime];
}
-(void)clearCache {
    [IJKFFMoviePlayerController clearCache];
}

- (void)log {
    //1. 根据当前环境设置日志信息
    //1.1如果是Debug状态的
#ifdef DEBUG
    //  设置报告日志
    [IJKFFMoviePlayerController setLogReport:YES];
    //  设置日志的级别为Debug
    [IJKFFMoviePlayerController setLogLevel:k_IJK_LOG_DEBUG];
    //1.2否则(如果不是debug状态的)
#else
    //  设置不报告日志
    [IJKFFMoviePlayerController setLogReport:NO];
    //  设置日志级别为信息
    [IJKFFMoviePlayerController setLogLevel:k_IJK_LOG_INFO];
#endif
    
    // 2. 检查版本是否匹配
    [IJKFFMoviePlayerController checkIfFFmpegVersionMatch:YES];
}


#pragma mark Install Movie Notifications

/* Register observers for the various movie object notifications. */
-(void)installMovieNotificationObservers
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(loadStateDidChange:)
                                                 name:IJKMPMoviePlayerLoadStateDidChangeNotification
                                               object:_player];
    
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(moviePlayBackDidFinish:)
                                                 name:IJKMPMoviePlayerPlaybackDidFinishNotification
                                               object:_player];
    
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(mediaIsPreparedToPlayDidChange:)
                                                 name:IJKMPMediaPlaybackIsPreparedToPlayDidChangeNotification
                                               object:_player];
    
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(moviePlayBackStateDidChange:)
                                                 name:IJKMPMoviePlayerPlaybackStateDidChangeNotification
                                               object:_player];
}
- (void)loadStateDidChange:(NSNotification*)notification
{
    //    MPMovieLoadStateUnknown        = 0,
    //    MPMovieLoadStatePlayable       = 1 << 0,
    //    MPMovieLoadStatePlaythroughOK  = 1 << 1, // Playback will be automatically started in this state when shouldAutoplay is YES
    //    MPMovieLoadStateStalled        = 1 << 2, // Playback will be automatically paused in this state, if started
    
    IJKMPMovieLoadState loadState = _player.loadState;
    
    if ((loadState & IJKMPMovieLoadStatePlaythroughOK) != 0) {
        NSLog(@"loadStateDidChange: IJKMPMovieLoadStatePlaythroughOK: %d\n", (int)loadState);
    } else if ((loadState & IJKMPMovieLoadStateStalled) != 0) {
        NSLog(@"loadStateDidChange: IJKMPMovieLoadStateStalled: %d\n", (int)loadState);
    } else {
        NSLog(@"loadStateDidChange: ???: %d\n", (int)loadState);
    }
}

- (void)moviePlayBackDidFinish:(NSNotification*)notification
{
    //    MPMovieFinishReasonPlaybackEnded,
    //    MPMovieFinishReasonPlaybackError,
    //    MPMovieFinishReasonUserExited
    int reason = [[[notification userInfo] valueForKey:IJKMPMoviePlayerPlaybackDidFinishReasonUserInfoKey] intValue];
    
    switch (reason)
    {
        case IJKMPMovieFinishReasonPlaybackEnded:
            NSLog(@"playbackStateDidChange: IJKMPMovieFinishReasonPlaybackEnded: %d\n", reason);
            break;
            
        case IJKMPMovieFinishReasonUserExited:
            NSLog(@"playbackStateDidChange: IJKMPMovieFinishReasonUserExited: %d\n", reason);
            break;
            
        case IJKMPMovieFinishReasonPlaybackError:
            NSLog(@"playbackStateDidChange: IJKMPMovieFinishReasonPlaybackError: %d\n", reason);
            break;
            
        default:
            NSLog(@"playbackPlayBackDidFinish: ???: %d\n", reason);
            break;
    }
}

- (void)mediaIsPreparedToPlayDidChange:(NSNotification*)notification
{
    NSLog(@"mediaIsPreparedToPlayDidChange\n");
}
- (void)moviePlayBackStateDidChange:(NSNotification*)notification
{
    //    MPMoviePlaybackStateStopped,
    //    MPMoviePlaybackStatePlaying,
    //    MPMoviePlaybackStatePaused,
    //    MPMoviePlaybackStateInterrupted,
    //    MPMoviePlaybackStateSeekingForward,
    //    MPMoviePlaybackStateSeekingBackward
    
    switch (_player.playbackState)
    {
        case IJKMPMoviePlaybackStateStopped: {
            NSLog(@"IJKMPMoviePlayBackStateDidChange %d: stoped", (int)_player.playbackState);
            break;
        }
        case IJKMPMoviePlaybackStatePlaying: {
            NSLog(@"IJKMPMoviePlayBackStateDidChange %d: playing", (int)_player.playbackState);
            break;
        }
        case IJKMPMoviePlaybackStatePaused: {
            NSLog(@"IJKMPMoviePlayBackStateDidChange %d: paused", (int)_player.playbackState);
            break;
        }
        case IJKMPMoviePlaybackStateInterrupted: {
            NSLog(@"IJKMPMoviePlayBackStateDidChange %d: interrupted", (int)_player.playbackState);
            break;
        }
        case IJKMPMoviePlaybackStateSeekingForward:
        case IJKMPMoviePlaybackStateSeekingBackward: {
            NSLog(@"IJKMPMoviePlayBackStateDidChange %d: seeking", (int)_player.playbackState);
            break;
        }
        default: {
            NSLog(@"IJKMPMoviePlayBackStateDidChange %d: unknown", (int)_player.playbackState);
            break;
        }
    }
}
#pragma mark Remove Movie Notification Handlers

/* Remove the movie notification observers from the movie object. */
-(void)removeMovieNotificationObservers
{
    [[NSNotificationCenter defaultCenter]removeObserver:self name:IJKMPMoviePlayerLoadStateDidChangeNotification object:_player];
    [[NSNotificationCenter defaultCenter]removeObserver:self name:IJKMPMoviePlayerPlaybackDidFinishNotification object:_player];
    [[NSNotificationCenter defaultCenter]removeObserver:self name:IJKMPMediaPlaybackIsPreparedToPlayDidChangeNotification object:_player];
    [[NSNotificationCenter defaultCenter]removeObserver:self name:IJKMPMoviePlayerPlaybackStateDidChangeNotification object:_player];
    [[NSNotificationCenter defaultCenter]removeObserver:self name:IJKMPMoviePlayerFirstVideoFrameRenderedNotification object:nil];
    
}

- (NSTimer *)presTrainTimer {
    if (!_presTrainTimer) {
        _presTrainTimer = [NSTimer scheduledTimerWithTimeInterval:.5 target:self selector:@selector(presTrainTimerRun) userInfo:nil repeats:YES];
        [[NSRunLoop mainRunLoop]addTimer:_presTrainTimer forMode:NSDefaultRunLoopMode];
    }
    return _presTrainTimer;
}
#pragma mark    ======== 预加载 ========
-(void)setPrestrainLastUrlWithString:(NSString *)urlStr {
    if (urlStr == nil) {
        return;
    }
    if (_prestrainLastPlayer) {
        [_prestrainLastPlayer shutdown];
        _prestrainLastPlayer = nil;
    }
    _prestrainLastPlayer = [[IJKFFMoviePlayerController alloc]initWithContentURLString:urlStr withOptions:_options];
    _prestrainLastPlayer.playbackVolume = 0;
    //如果主要播放器正在播放，直接开始准备播放
    if ([_player isPlaying]) {
        [_prestrainLastPlayer prepareToPlay];
    }
    
    
    [self.presTrainTimer fire];
}
-(void)setPrestrainUrlWithString:(NSString *)urlStr {
    if (urlStr == nil) {
        return;
    }
    
    if (_prestrainPlayer) {
        [_prestrainPlayer shutdown];
        _prestrainPlayer = nil;
    }
    _prestrainPlayer = [[IJKFFMoviePlayerController alloc]initWithContentURLString:urlStr withOptions:_options];
    _prestrainPlayer.playbackVolume = 0;
    //如果主要播放器正在播放，直接开始准备播放
    if ([_player isPlaying]) {
        [_prestrainPlayer prepareToPlay];
    }
    
    [self.presTrainTimer fire];
}
//自第一timer，当预加载的player达到一定值是shutdown
-(void)presTrainTimerRun {
    
    CGFloat nableDuration = _prestrainPlayer.playableDuration/_prestrainPlayer.duration;
    if (nableDuration > 0.15) {
        [_prestrainPlayer shutdown];
        NSLog(@"presTrainTimer shutdown  _prestrainPlayer");
    }
    
    CGFloat lastenableDuration = _prestrainLastPlayer.playableDuration/_prestrainLastPlayer.duration;
    NSLog(@"presTrainTimerRun lastenableDuration %f   %f    %f",lastenableDuration ,_prestrainLastPlayer.playableDuration, _prestrainLastPlayer.duration);
    NSLog(@"presTrainTimerRun nableDuration %f",nableDuration);
    if (lastenableDuration > 0.15) {
        [_prestrainLastPlayer shutdown];
        //            [_presTrainTimer invalidate];
        //            _presTrainTimer = nil;
        NSLog(@"presTrainTimer shutdown  _prestrainLastPlayer");
    }
    
    
    
}
//首帧显示，原播放的player显示后开始加载其他预加载的player
- (void)movieFirstVideoFrameRendered:(NSNotification*)notification
{
    if (notification.object == self.player) {
        
        [_prestrainPlayer prepareToPlay];
        [_prestrainLastPlayer prepareToPlay];
        
        
    }
    //预加载的player显示首帧后暂停
    if (notification.object == self.prestrainPlayer) {
        
        [_prestrainPlayer pause];
        
        
    }
    if (notification.object == self.prestrainLastPlayer) {
        
        [_prestrainLastPlayer pause];
        
        
    }
}



-(void)awakeFromNib
{
    [super awakeFromNib];
}


@end
